﻿using HalconDotNet;
using HslCommunication;
using NDK.AcqDevice.HikVision;
using NDK.Module.Model;
using NDK.Motion.MachineResources;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using VisionPlatform;

namespace NDK.Module.StationLogic
{
    public abstract class StationLogic : StationLogicBase
    {
        public Stopwatch FlowCT;

        public Stopwatch WaitCT;

        public MvCameraController MVCCD = null;
        /// <summary>
        /// 相机拍照图片
        /// </summary>
        public HImage HImageCCD = null;
        /// <summary>
        /// 
        /// </summary>
        public static HImage HCCDTest = null;

        #region  属性
        /// <summary>
        /// 拍照失败计数
        /// </summary>
        public int PhotoFailureCount { get; set; }
        /// <summary>
        /// 返回PLC操作结果
        /// </summary>
        public OperateResult PLCOperateResult { get; set; } = null;
        /// <summary>
        /// 算法实例
        /// </summary>
        public VisionManager.Engine VisionEngine { get; set; } = null;
        /// <summary>
        /// SN队列
        /// </summary>
        public ConcurrentQueue<string> QueueSN { get; set; } = null;
        /// <summary>
        /// 图像队列
        /// </summary>
        public ConcurrentQueue<MeasureImage> QueueImage { get; set; } = null;
        public ConcurrentQueue<MeasureImage> QueueImage1 { get; set; } = null;
        /// <summary>
        /// 工位请求放料信号
        /// </summary>
        public bool SignalRequest { get; set; } = false;

        /// <summary>
        /// 下料搬运放料
        /// </summary>
        public bool SignalRequest1 { get; set; } = false;


        /// <summary>
        /// 转盘下料取料
        /// </summary>
        public bool SignalRequest2 { get; set; } = false;

        /// <summary>
        /// 工位完成信号
        /// </summary>
        public bool SignalComplete { get; set; } = false;


        /// <summary>
        /// 下激光取图完成
        /// </summary>
        public bool SignalComplete1 { get; set; } = false;

        public bool GRRSignalComplete { get; set; } = false;
        public bool GRRSignalRequest { get; set; } = false;

        public int StationID { get; set; }

        public int CurHoleId { get; set; }

        private string _VisionFlowName;

        public string VisionFlowName
        {
            get { return _VisionFlowName; }
            set { _VisionFlowName = value; }
        }

        public string VisionOutPutName { get => $"{_VisionFlowName}Data"; }

        private string _VisionFlowName1;

        public string VisionFlowName1
        {
            get { return _VisionFlowName1; }
            set { _VisionFlowName1 = value; }
        }

        public string VisionOutPutName1 { get => $"{_VisionFlowName1}Data"; }

        private string _VisionFlowName2;

        public string VisionFlowName2
        {
            get { return _VisionFlowName2; }
            set { _VisionFlowName2 = value; }
        }

        public string VisionOutPutName2 { get => $"{_VisionFlowName2}Data"; }
        #endregion



        public override void Init ()
        {
            SignalRequest = false;
            SignalComplete = false;
            base.Init();
        }

        /// <summary>
        /// 气缸同步运动函数
        /// </summary>
        /// <param name="isWork">Work Or Home</param>
        /// <param name="cylinders">1.当前需要控制的气缸 2.是否屏蔽</param>
        /// <returns></returns>
        public bool CylinderMethod (bool isWork, params (DoubleDriveCylinder, bool)[] cylinders)
        {
            List<Task<(string, bool)>> tasks = new List<Task<(string, bool)>>();
            foreach(var item in cylinders)
            {
                tasks.Add(Task.Run(() => Work(item)));
            }
            Task.WaitAll(tasks.ToArray());

            var taskbool = tasks.FindAll(task => task.Result.Item2 == true);
            if(taskbool.Count > 0)
            {
                string mes = string.Empty;
                taskbool.ForEach(x => mes += $"{x.Result.Item1} ");
                return AlarmPause("气缸异常", $"{mes}{(isWork ? "动点" : "原点")}位异常,请检查", "调试气缸信号", "重新检测", "忽略报警，继续运行") != DialogResult.OK;
            }
            return true;


            (string, bool) Work ((DoubleDriveCylinder, bool) cylinder)
            {
                (string, bool) re = (cylinder.Item1.Name, false);
                if(cylinder.Item2)
                {
                    _ = isWork ? cylinder.Item1.Work() : cylinder.Item1.Home();
                    bool IsTimeOut = isWork ? cylinder.Item1.WaitWork(2000) : cylinder.Item1.WaitHome(2000);
                    re.Item2 = IsTimeOut;
                }
                return re;
            }
        }

        /// <summary>
        /// 真空同步动作函数
        /// </summary>
        /// <param name="isON"> On or Off</param>
        /// <param name="vacuums">1.真空输出 2.真空反馈 3.是否屏蔽</param>
        /// <returns></returns>
        public bool VacuumMethod (bool isON, params (OutputSetting, InputSetting, bool)[] vacuums)
        {
            List<Task<(string, bool)>> tasks = new List<Task<(string, bool)>>();
            foreach(var item in vacuums)
            {
                tasks.Add(Task.Run(() => Work(item)));
            }
            Task.WaitAll(tasks.ToArray());
            var isOK = tasks.FindAll(x => x.Result.Item2 == true);
            if(isOK.Count > 0)
            {
                string mes = string.Empty;
                tasks.ForEach(x => mes += $"{x.Result.Item1}{(isON ? "打开" : "关闭")}异常 ");
                return AlarmPause("吸真空报警", $"{mes}，请检查", "调试真空信号", "重新检测", "忽略报警，继续运行") != DialogResult.OK;
            }
            return true;

            (string, bool) Work ((OutputSetting, InputSetting, bool) vacuum)
            {
                (string, bool) re = (vacuum.Item2.Name, false);
                if(vacuum.Item3)
                {
                    _ = isON ? vacuum.Item1.ON() : vacuum.Item1.OFF();
                    if(!Common.BP_屏蔽信号检测)
                    {
                        bool isWork = isON ? vacuum.Item2.WaitON(3000) : false;
                        re.Item2 = isWork;
                    }
                }
                return re;
            }
        }

        /// <summary>
        /// PLC同步写入函数
        /// </summary>
        /// <param name="station">当前写入工站</param>
        /// <param name="plcs">1.写入地址 2.True Or False</param>
        /// <returns></returns>
        public bool PLCWriteMethod (string station, params (string, bool?, float?)[] plcs)
        {
            List<Task<(string, bool)>> tasks = new List<Task<(string, bool)>>();
            foreach(var item in plcs)
            {
                if(item.Item2 != null)
                {
                    tasks.Add(Task.Run(() =>
                    Common.OmronPLC.Write(item.Item1, (bool)item.Item2).IsSuccess ? (string.Empty, true) : (item.Item1, false)));
                }
                else if(item.Item3 != null)
                {

                    tasks.Add(Task.Run(() => Common.OmronPLC.Write(item.Item1, (float)item.Item3).IsSuccess ? (string.Empty, true) : (item.Item1, false)));
                }
            }
            Task.WaitAll(tasks.ToArray());
            var IsOk = tasks.FindAll(x => x.Result.Item2 == false);
            if(IsOk.Count > 0)
            {
                string mes = string.Empty;
                tasks.ForEach(x => mes += $"{x.Result.Item1} ");
                return AlarmPause("写PLC异常", $"{station},写入地址", "写PLC异常，请检查", "重新写入", "忽略报警，继续运行") != DialogResult.OK;
            }
            return true;
        }
        /// <summary>
        /// 写入int值
        /// </summary>
        /// <param name="station"></param>
        /// <param name="plcs"></param>
        /// <returns></returns>
        public bool PLCWriteMethodInt (string station, params (string, int)[] plcs)
        {
            List<Task<(string, bool)>> tasks = new List<Task<(string, bool)>>();
            foreach(var item in plcs)
            {

                tasks.Add(Task.Run(() => Common.OmronPLC.Write(item.Item1, item.Item2).IsSuccess ? (string.Empty, true) : (item.Item1, false)));

            }
            Task.WaitAll(tasks.ToArray());
            var IsOk = tasks.FindAll(x => x.Result.Item2 == false);
            if(IsOk.Count > 0)
            {
                string mes = string.Empty;
                tasks.ForEach(x => mes += $"{x.Result.Item1} ");
                return AlarmPause("写PLC异常", $"{station},写入地址", "写PLC异常，请检查", "重新写入", "忽略报警，继续运行") != DialogResult.OK;
            }
            return true;
        }
        /// <summary>
        /// CCD拍照
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public bool CCDImage (ref HImage image)
        {
            PhotoFailureCount = 0;
            do
            {
                MVCCD?.Snap();
                PhotoFailureCount++;
                image = MVCCD?.HalconImage();
                if(image == null)
                {
                    Thread.Sleep(500);
                }
            } while(PhotoFailureCount < 3 && image == null);

            if(image == null)
            {
                if(AlarmPause("采图异常", "量测CCD图像连续三次采集异常：", "请检查相机是否掉线及相机参数是否存在异常", " 再次拍照", "忽略继续") == DialogResult.OK)
                {
                    //PublicMethod.ReconnectCam(ref MVCCD, MVCCDName);
                    return false;
                }
            }
            return true;
        }

        public void UICtLog (string flow)
        {
            if(!Common.BP_是否屏蔽计时 && FlowCT != null)
            {
                Common.AppendUiLog.Log($"[{logBaseInfo}] -->[{flow}] 用时: {FlowCT.ElapsedMilliseconds} ms");
            }
        }

        public void UICtLog1(string flow)
        {
            if (!Common.BP_是否屏蔽计时)
            {
                Common.AppendUiLog.Log(flow);
            }
        }
    }
}
